 package com.gmrz.uaf.crypto.internal.handlers;
 
 import com.google.common.primitives.Bytes;
 import com.gmrz.uaf.common.UAFRuntimeException;
 import com.gmrz.uaf.crypto.CryptoConfig;
 import com.gmrz.uaf.crypto.spi.handlers.HMACHandler;
 import com.gmrz.util.Convert;
 import java.security.GeneralSecurityException;
 import java.security.Key;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import javax.crypto.Mac;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 import org.apache.commons.lang3.ArrayUtils;
 
 public class DefaultHMACHandler
   implements HMACHandler
 {
   private static final String HMAC_ALGO_SHA256 = "HmacSHA256";
   private static final String HASH_ALGO = "SHA-256";
   private SecretKey encryptionSecretKey = null;
 
   public DefaultHMACHandler(CryptoConfig cryptoConfig) {
     initKey(cryptoConfig);
   }
 
   public byte[] hmac(byte[] data) throws GeneralSecurityException
   {
     Mac mac = Mac.getInstance(HMAC_ALGO_SHA256);
     mac.init(getKey());
     return mac.doFinal(data);
   }
 
   private Key getKey() {
     if (this.encryptionSecretKey == null) {
       throw new UAFRuntimeException("External encryption key for HMAC has not been initialized.");
     }
     return this.encryptionSecretKey;
   }
 
   private void initKey(CryptoConfig cryptoConfig)
   {
     byte[] rawExternalEncryptionKey = cryptoConfig.getExternalEncryptionKey();
 
     byte[] fixedSalt = Convert.fromBase64("HmacHandleSalt");
 
     rawExternalEncryptionKey = Bytes.concat(rawExternalEncryptionKey, fixedSalt);
 
     MessageDigest digest = null;
     try {
       digest = MessageDigest.getInstance(HASH_ALGO);
     } catch (NoSuchAlgorithmException e) {
       throw new UAFRuntimeException("Hashing failed.", e);
     }
 
     if (digest == null) {
       throw new UAFRuntimeException("Hashing failed due to null digest instance.");
     }
     rawExternalEncryptionKey = digest.digest(rawExternalEncryptionKey);
 
     String keyAlgorithm = cryptoConfig.getExternalHmacKeyAlgo();
 
     if (ArrayUtils.isEmpty(rawExternalEncryptionKey)) {
       throw new UAFRuntimeException("External encryption key cannot be empty.");
     }
 
     if (rawExternalEncryptionKey.length < 32) {
       throw new UAFRuntimeException("External encryption key does not match minimum length criteria.");
     }
 
     this.encryptionSecretKey = new SecretKeySpec(rawExternalEncryptionKey, keyAlgorithm);
   }
 }
